home *** CD-ROM | disk | FTP | other *** search
/ Alles Voor Internet / Tout Pour Internet / alles voor internet.iso / MacInternet™ / Telnet / NCSA / tn3270 2.4d7 source / tn3270 / writetm.c < prev   
Text File  |  1992-04-17  |  15KB  |  646 lines

  1. /*
  2.  *  tn3270 for the Macintosh Source Code
  3.  *  Brown University Computing and Information Services
  4.  *  Version 2.4d7  April, 1992
  5.  *  Copyright (c) 1988, 1989, 1990, 1991, 1992 by Brown University and by
  6.  *  Peter John DiCamillo.
  7.  *
  8.  *  Permission is granted to any individual or institution to use, copy,
  9.  *  or redistribute the binary version of this software and its
  10.  *  documentation provided this notice and the copyright notices are
  11.  *  retained.  Permission is granted to any individual or non-profit
  12.  *  institution to use, copy, modify, or redistribute the source files
  13.  *  of this software provided this notice and the copyright notices are
  14.  *  retained.  This software may not be distributed for profit, either
  15.  *  in original form or in derivative works, nor can the source be
  16.  *  distributed to other than an individual or a non-profit institution.
  17.  *  Any  individual or group interested in seeing and/or using these
  18.  *  source files but who are prevented from doing so by the above
  19.  *  constraints should contact Don Wolfe, Assistant Vice-President for
  20.  *  Computer Systems at Brown University, (401) 863-7250, for possible
  21.  *  software licensing of the source developed at Brown.
  22.  *
  23.  *  Brown University and Peter John DiCamillo make no representations
  24.  *  about the suitability of this software for any purpose.
  25.  *
  26.  *  BROWN UNIVERSITY AND PETER JOHN DICAMILLO GIVE NO WARRANTY, EITHER
  27.  *  EXPRESS OR IMPLIED, FOR THE PROGRAM AND/OR DOCUMENTATION PROVIDED,
  28.  *  INCLUDING, WITHOUT LIMITATION, WARRANTY OF MERCHANTABILITY AND
  29.  *  WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE.
  30.  *
  31.  */
  32.  
  33. #if !defined(USEDUMP)
  34.     #include "maclib.h"
  35.     #include "termdef.h"
  36.     #include "tn3270funcs.h"
  37.     #include "globals.h"
  38. #else
  39.     #pragma load "tn3270DumpFile"
  40. #endif
  41.  
  42. #pragma segment 3270seg1
  43.  
  44. extern unsigned char ordertab[];
  45.  
  46. void writetm(unsigned char *cmd, short len, char init, cnr *cp)
  47. {
  48. register short left;
  49. register short size;
  50. register unsigned char c, ew;
  51.  
  52. cp->savedvalid = 0;                /* getattr saved info. may be invalid now */
  53.  
  54. if (init) {
  55.     ew = 0;                        /* erase/write flag */                     
  56.     if ((cmd[0] & 0x07) >= 5) {        /* interpret op-code */
  57.         ew = 1;
  58.         if (cp->skipnewmode == 0) {
  59.             if (((cmd[0] & 0x0f) == 0x0d) || (cmd[0] == 0x7e)) {    /* ewa */
  60.                 cp->ewamode = 1;
  61.                 }
  62.             else {                        /* possible end of ewa */
  63.                 cp->ewamode = 0;
  64.                 }
  65.             newmode(cp->ewamode, 0, cp);
  66.             }
  67.         clrscn(cp);
  68.         }
  69.     intwcc(ew, cmd[1], cp);            /* interpret WCC */
  70.     cp->ldvoff = 2;                    /* skip to start of data */
  71.     cp->ptfill = 0;
  72.     cp->chratr = 0;
  73.     cp->bufadr = cp->curadr;            /* buffer address starts out at cursor */
  74.     }
  75.  
  76. while (cp->ldvoff < len) {
  77.                                 /* special code to handle data quickly */
  78.     c = cmd[cp->ldvoff++];
  79.     if (ordertab[c]) {
  80.         (cp->chrbuff)[cp->bufadr] = c;
  81.         (cp->atrbuff)[cp->bufadr] = cp->chratr;
  82.         if ((c == 0xad) || (c == 0xbd))
  83.             if (cp->fixbracket) (cp->atrbuff)[cp->bufadr] += 0x4000;
  84.         cp->bufadr++;
  85.         if (cp->bufadr == cp->maxcnt) cp->bufadr = 0;
  86.         cp->ptfill = 1;
  87.         continue;
  88.         }
  89.     else cp->ldvoff--;
  90.                                 /* order processing code */
  91.     left = len - cp->ldvoff;
  92.     switch(cmd[cp->ldvoff]) {
  93.         case 0x1D:        /* Start Field */
  94.                 if (left < 2) return;
  95.                 intsf(cmd[cp->ldvoff+1], cp);
  96.                 cp->ldvoff += 2;
  97.                 cp->ptfill = 0;
  98.                 break;
  99.  
  100.         case 0x11:        /* Set Buffer Address */
  101.                 if (left < 3) return;
  102.                 intsba(cmd[cp->ldvoff+1], cmd[cp->ldvoff+2], cp);
  103.                 cp->ldvoff += 3;
  104.                 cp->ptfill = 0;
  105.                 break;
  106.  
  107.         case 0x13:        /* Insert Cursor */
  108.                 intic(cp);
  109.                 cp->ldvoff++;
  110.                 cp->ptfill = 0;
  111.                 break;
  112.  
  113.         case 0x05:        /* Program Tab */
  114.                 intpt(cp);
  115.                 cp->ldvoff++;
  116.                 break;
  117.  
  118.         case 0x3C:        /* Repeat to Address */
  119.                 if (left < 4) return;
  120.                 c = cmd[cp->ldvoff+3];
  121.                 if (c == 0x08) {
  122.                    if (left < 5) return;
  123.                    c = cmd[cp->ldvoff+4];
  124.                    intra(cmd[cp->ldvoff+1], cmd[cp->ldvoff+2], c, 1, cp);
  125.                    cp->ldvoff += 5;
  126.                    }
  127.                 else {
  128.                    intra(cmd[cp->ldvoff+1], cmd[cp->ldvoff+2], c, 0, cp);
  129.                    cp->ldvoff += 4;
  130.                    }
  131.                 cp->ptfill = 0;
  132.                 break;
  133.  
  134.         case 0x12:        /* Erase Unprotected to Address */
  135.                 if (left < 3) return;
  136.                 inteua(cmd[cp->ldvoff+1], cmd[cp->ldvoff+2], cp);
  137.                 cp->ldvoff += 3;
  138.                 cp->ptfill = 0;
  139.                 break;
  140.  
  141.         case 0x08:        /* Graphics Escape */
  142.                 if (left < 2) return;
  143.                 intdata(cmd[cp->ldvoff+1], 1, cp);
  144.                 cp->ldvoff += 2;
  145.                 break;
  146.  
  147.         case 0x29:        /* Start Field Extended */
  148.                 if (left < 2) return;
  149.                 size = (cmd[cp->ldvoff+1]+1) * 2;
  150.                 if (left < size) return;
  151.                 intsfe(cmd+cp->ldvoff+2, cmd[cp->ldvoff+1], cp);
  152.                 cp->ldvoff += size;
  153.                 cp->ptfill = 0;
  154.                 break;
  155.  
  156.         case 0x2C:        /* Modify Field */
  157.                 if (left < 2) return;
  158.                 size = (cmd[cp->ldvoff+1]+1) * 2;
  159.                 if (left < size) return;
  160.                 intmf(cmd+cp->ldvoff+2, cmd[cp->ldvoff+1], cp);
  161.                 cp->ldvoff += size;
  162.                 cp->ptfill = 0;
  163.                 break;
  164.  
  165.         case 0x28:        /* Set Attribute */
  166.                 if (left < 3)  return;
  167.                 intsa(cmd[cp->ldvoff+1], cmd[cp->ldvoff+2], cp);
  168.                 cp->ldvoff += 3;
  169.                 cp->ptfill = 0;
  170.                 break;
  171.  
  172.         default:        /* shouldn't happen */
  173.                 break;
  174.         }
  175.     }
  176. }
  177.  
  178. void clrscn(cnr *cp)
  179. {
  180. memset(cp->chrbuff, 0, cp->maxcnt);
  181. memset(cp->atrbuff, 0, cp->maxcnt<<1);
  182. cp->curadr = 0;
  183. cp->bufadr = 0;
  184. cp->colorfield = 0;
  185. cp->textsel = 0;
  186. cp->fmtscrn = 0;
  187. }
  188.  
  189. void intwcc(unsigned char ew, unsigned char wcc, cnr *cp)
  190. {
  191. register short i;
  192.  
  193. cp->lastwcc = wcc & 0x7f;
  194. if (wcc & 0x01) for (i=0; i < cp->maxcnt; i++) {
  195.     (cp->atrbuff)[i] &= 0xFEFF;
  196.     }
  197. cp->kb_err = 0;
  198. if (cp->kblock) {
  199.     cp->lastwcc |= 0x80;    /* remember was locked */
  200.                         /* indicate SYSTEM immediately */
  201.     if ((cp->kblcode == 2) && ((wcc & 0x02) == 0)) {
  202.         cp->kblcode = 1;
  203.         newstat(cp);
  204.         }
  205.     }
  206. else {
  207.     cp->kblock = 1;
  208.     cp->kblcode = 2;
  209.     newstat(cp);
  210.     }
  211. if (ew) if (wcc & 0x40)            /* wcc reset in EW/EWA */
  212.     clrpict(cp);                /* erase graphics */
  213. }
  214.  
  215. void endwcc(cnr *cp)
  216. {
  217. if (cp->lastwcc & 0x04) if (!(cp->tcpflg)) beep(cp);
  218.                         else cp->pndbeep = 1;
  219. if (cp->lastwcc & 0x02) cp->rdaid = 0x60;    /* reset last AID */
  220. if (cp->cs.curpos) {
  221.     cp->x = cp->curadr%cp->scrhsize;
  222.     cp->y = cp->curadr/cp->scrhsize;
  223.     }
  224. if ((cp->lastwcc & 0x82) != 0x80) {
  225.     cp->kblock = 0;
  226.     cp->kblcode = 0;
  227.     newstat(cp);
  228.     }
  229. else if (cp->cs.curpos) newstat(cp);
  230.  
  231. checkfmt(cp);            /* check that fmtscrn is still correct */
  232. }
  233.  
  234. void checkfmt(cnr *cp)     /* check all attributes have not been overwritten by data */
  235. {
  236. register short i;
  237.                 /* unformatted is always correct */
  238. if (cp->fmtscrn == 0) return;
  239.                 /* formatted if attribute where we last put one */
  240. if ((cp->atrbuff)[cp->attrloc] & 0x8000) return;
  241.                 /* else look for an attribute byte */
  242. for (i=0; i < cp->maxcnt; i++)
  243.     if ((cp->atrbuff)[i] & 0x8000) return;
  244.                 /* all attributes were overwritten: reset flag */
  245. cp->fmtscrn = 0;
  246. }
  247.  
  248. void intsf(unsigned char attr, cnr *cp)
  249. {
  250.  
  251. (cp->chrbuff)[cp->bufadr] = 0x1d;
  252. (cp->atrbuff)[cp->bufadr] = 0x8000 + ((attr & 0x3f) << 8);
  253. cp->attrloc = cp->bufadr;
  254. cp->bufadr++;
  255. if (cp->bufadr == cp->maxcnt) cp->bufadr = 0;
  256. cp->fmtscrn = 1;
  257. }
  258.  
  259. void intsba(unsigned char a1, unsigned char a2, cnr *cp)
  260. {
  261. cp->bufadr = cvtadr(a1, a2, cp);
  262. }
  263.  
  264. void intic(cnr *cp)
  265. {
  266. cp->curadr = cp->bufadr;
  267. }
  268.  
  269. void intpt(cnr *cp)
  270. {
  271. register unsigned short a; 
  272.  
  273. while (true) {            /* loop through protected fields */
  274.     while (!((cp->atrbuff)[cp->bufadr] & 0x8000)) {    /* get to next attribute */
  275.         if (cp->ptfill) setnull(cp);        /* fill with nulls if set */
  276.         else {
  277.             cp->bufadr++;
  278.             if (cp->bufadr == cp->maxcnt) cp->bufadr = 0;
  279.             }
  280.         if (cp->bufadr == 0) return;
  281.         }
  282.     cp->ptfill = 0;                    /* no nulls after first field */
  283.     a = (cp->atrbuff)[cp->bufadr];        /* get attributes for this field */
  284.     cp->bufadr++;                    /* increment buffer address */
  285.     if (cp->bufadr == cp->maxcnt) {
  286.         cp->bufadr = 0;                /* done if wrapped */
  287.         return;
  288.         }
  289.     if (!(a & 0x2000)) return;    /* found field if unprotected */
  290.     }
  291. }
  292.  
  293. void intra(unsigned char a1, unsigned char a2,
  294.            unsigned char c, unsigned char g, cnr *cp)
  295. {
  296. register short endadr;
  297.  
  298. endadr = cvtadr(a1, a2, cp);
  299. do intdata(c, g, cp); while (endadr != cp->bufadr);
  300. }
  301.  
  302. void inteua(unsigned char a1, unsigned char a2, cnr *cp)
  303. {
  304. register unsigned char skip, nofmt;
  305. register short endadr, addr, prot;
  306.  
  307. endadr = cvtadr(a1, a2, cp);
  308. addr = cp->bufadr;            /* find previous attribute */
  309. nofmt = 0;
  310. while (!((cp->atrbuff)[addr] & 0x8000)) {
  311.     if (addr == 0) {
  312.         nofmt = 1;
  313.         break;
  314.         }
  315.     else addr--;
  316.     }
  317. if (nofmt) prot = 0;
  318. else prot = (cp->atrbuff)[addr] & 0x2000;
  319. skip = 0;
  320. do {
  321.     if ((cp->atrbuff)[cp->bufadr] & 0x8000) {
  322.         prot = (cp->atrbuff)[cp->bufadr] & 0x2000;
  323.         skip = 1;
  324.         }
  325.     else if (!prot) {
  326.         if (skip) {
  327.             skip = 0;
  328.             }
  329.         setnull(cp);
  330.         }
  331.          else skip = 1;
  332.     if (skip) {
  333.         cp->bufadr++;
  334.         if (cp->bufadr == cp->maxcnt) cp->bufadr = 0;
  335.         }
  336.     } while (endadr != cp->bufadr);
  337. }
  338.  
  339. void intsfe(unsigned char *field, unsigned char pairs, cnr *cp)
  340. {
  341. (cp->atrbuff)[cp->bufadr] = intpairs(0x8000, field, pairs, cp);
  342. (cp->chrbuff)[cp->bufadr] = 0x1d;
  343. cp->attrloc = cp->bufadr;
  344. cp->bufadr++;
  345. if (cp->bufadr == cp->maxcnt) cp->bufadr = 0;
  346. cp->fmtscrn = 1;
  347. }
  348.  
  349. void intmf(unsigned char *field, unsigned char pairs, cnr *cp)
  350. {
  351. register short atr;
  352.  
  353. atr = intpairs((cp->atrbuff)[cp->bufadr], field, pairs, cp);
  354. if (atr & 0x8000) {
  355.     (cp->atrbuff)[cp->bufadr] = atr;
  356.     (cp->chrbuff)[cp->bufadr] = 0x1d;
  357.     }
  358. cp->bufadr++;
  359. if (cp->bufadr == cp->maxcnt) cp->bufadr = 0;
  360. }
  361.  
  362. void intsa(unsigned char type, unsigned char value, cnr *cp)
  363. {
  364. register unsigned char safield[2];
  365.  
  366. if ((type == 0) && (value == 0)) {
  367.     cp->chratr = 0;
  368.     return;
  369.     }
  370. safield[0] = type;
  371. safield[1] = value;
  372. cp->chratr = intpairs(cp->chratr, safield, 1, cp);
  373. }
  374.  
  375. unsigned short intpairs(unsigned short atr, unsigned char *field,
  376.               unsigned char pairs, cnr *cp)
  377. {
  378. register unsigned char c;
  379. register short offset;
  380.  
  381. offset = 0;
  382. while (pairs > 0) {
  383.     c = field[offset+1];
  384.     switch(field[offset]) {
  385.  
  386.     case 0xC0:    atr &= 0xC0FF;
  387.             atr += (c & 0x3f) << 8;
  388.             break;
  389.  
  390.     case 0x41:    atr &= 0xFFE7;
  391.             if (c ==  0xF4) c = 0xF3;
  392.             atr += (c & 0x03) << 3;
  393.             break;
  394.  
  395.     case 0x42:    atr &= 0xFFF8;
  396.             if ((c & 0x07) == 0) break;
  397.             /* if (c == 0) c = 0xF4; */
  398.             atr += c & 0x07;
  399.             cp->colorfield = 1;
  400.             break;
  401.     case 0x43:    atr &= 0xFF3F;
  402.             atr += (c & 0x03) << 6;
  403.             break;
  404.     default:    break;
  405.     }
  406.     offset += 2;
  407.     pairs--;
  408.     }
  409. return(atr);
  410. }
  411.  
  412. void intdata(unsigned char code, unsigned char geflag, cnr *cp)
  413. (cp->chrbuff)[cp->bufadr] = code;
  414. (cp->atrbuff)[cp->bufadr] = cp->chratr;
  415. if ((code == 0xad) || (code == 0xbd))
  416.     if (cp->fixbracket) geflag = 1;
  417. if (geflag) (cp->atrbuff)[cp->bufadr] += 0x4000;
  418. cp->bufadr++;
  419. if (cp->bufadr == cp->maxcnt) cp->bufadr = 0;
  420. }
  421.  
  422. void setnull(cnr *cp)
  423. {
  424. (cp->chrbuff)[cp->bufadr] = 0;
  425. (cp->atrbuff)[cp->bufadr] = 0;
  426. cp->bufadr++;
  427. if (cp->bufadr == cp->maxcnt) cp->bufadr = 0;
  428. }
  429.  
  430. short cvtadr(unsigned char a1, unsigned char a2, cnr *cp)
  431. {
  432. short a;
  433.  
  434. if ((a1 & 0xc0) == 0)        /* 14-bit address */
  435.     a = (a1 << 8) + a2;
  436. else a = ((a1 & 0x3f) << 6) + (a2 & 0x3f);    /* 12-bit address */
  437. if (a < 0) a = 0;
  438. if (a > cp->maxoff) a = cp->maxoff;
  439. return(a);
  440. }
  441.  
  442. void orderinit(void)
  443. {
  444. register short i, j;
  445. static unsigned char ordercodes[] =
  446.     {0x1d, 0x11, 0x13, 0x05, 0x3c, 0x12, 0x08, 0x29, 0x2c, 0x28, 0x00};
  447.  
  448. for (i=0; i < 256; i++) ordertab[i] = 0xff;
  449. j = strlen(ordercodes);
  450. for (i=0; i < j; i++) ordertab[ordercodes[i]] = 0;
  451. }
  452.  
  453. void setrectsel(short offset1, short offset2, cnr *cp)
  454. {
  455. short rowmin, rowmax, colmin, colmax, t;
  456. register short row, col;
  457.  
  458. if (offset1 == offset2) return;
  459. rowmin = offset1 / cp->scrhsize;
  460. colmin = offset1 % cp->scrhsize;
  461. rowmax = offset2 / cp->scrhsize;
  462. colmax = offset2 % cp->scrhsize;
  463. if (rowmin > rowmax) {
  464.     t = rowmax;
  465.     rowmax = rowmin;
  466.     rowmin = t;
  467.     }
  468. if (colmin > colmax) {
  469.     t = colmax;
  470.     colmax = colmin;
  471.     colmin = t;
  472.     }
  473. for (row = rowmin; row <= rowmax; row++)
  474.     for (col = colmin; col <= colmax; col++) {
  475.         if ((cp->atrbuff)[cp->scrhsize*row + col] ^= 0x0020) cp->textsel = 1;
  476.         }
  477. invldscr(cp);
  478. }
  479.  
  480. void settextsel(short offset1, short offset2, char invert, cnr *cp)
  481. {
  482. short start, end, offset;
  483.  
  484. start = offset1;
  485. end = offset2;
  486. if (end < start) {
  487.     start = offset2;
  488.     end = offset1;
  489.     }
  490. for (offset = start; offset < end; offset++) {
  491.     if (invert) {
  492.         (cp->atrbuff)[offset] ^= 0x0020;
  493.         }
  494.     else {
  495.         (cp->atrbuff)[offset] |= 0x0020;
  496.         }
  497.     cp->textsel = 1;
  498.     }
  499. invldscr(cp);
  500. }
  501.  
  502. void addfieldsel(cnr *cp)     /* select entire field for any field partly selected */
  503. {
  504. register short i;
  505. short firstpos, attrpos;
  506. char selflag;
  507.  
  508. if (!(cp->fmtscrn)) return;
  509.  
  510. firstpos = 0;
  511. /* if first byte not an attribute, find attribute for first byte */
  512. if (((cp->atrbuff)[0] & 0x8000) == 0) {
  513.     firstpos = -1;
  514.     for (i = cp->maxoff; i > 0; i--)
  515.         if ((cp->atrbuff)[i] & 0x8000) {
  516.             firstpos = i;
  517.             break;
  518.             }
  519.     }
  520. if (firstpos < 0) return;
  521.  
  522. /* set selection bit for the attribute byte of each field to be selected */
  523. attrpos = firstpos;
  524. for (i=0; i < cp->maxcnt; i++)
  525.     if ((cp->atrbuff)[i] & 0x8000) {        /* attribute byte */
  526.         attrpos = i;
  527.         }
  528.     else {                            /* data byte */
  529.         if ((cp->atrbuff)[i] & 0x0020) (cp->atrbuff)[attrpos] |= 0x0020;
  530.         }
  531.  
  532. /* set selections bits for all bytes in selected fields */
  533. selflag = ((cp->atrbuff)[firstpos] & 0x0020) == 0x0020;
  534. for (i=0; i < cp->maxcnt; i++)
  535.     if ((cp->atrbuff)[i] & 0x8000) {        /* attribute byte */
  536.         selflag = ((cp->atrbuff)[i] & 0x0020) == 0x0020;
  537.         }
  538.     else {
  539.         if (selflag) (cp->atrbuff)[i] |= 0x0020;
  540.         }
  541.  
  542. /* reset selection bits in the field attributes */
  543. for (i=0; i < cp->maxcnt; i++)
  544.     if ((cp->atrbuff)[i] & 0x8000) (cp->atrbuff)[i] &= 0xffdf;
  545. }
  546.  
  547. void resetsel(cnr *cp)
  548. {
  549. register short i;
  550. char selflag;
  551.  
  552. selflag = 0;
  553. for (i = 0; i < cp->maxcnt; i++) {
  554.     if ((cp->atrbuff)[i] & 0x0020) {
  555.         selflag = 1;
  556.         (cp->atrbuff)[i] &= 0xffdf;
  557.         }
  558.     }
  559. cp->textsel = 0;
  560. if (selflag) invldscr(cp);
  561. }
  562.  
  563. void checksel(cnr *cp)        /* check if there really is selected text */
  564. {
  565. register short i;
  566.  
  567. cp->textsel = 0;
  568. for (i=0; i < cp->maxcnt; i++) {
  569.     if ((cp->atrbuff)[i] & 0x0020) {
  570.         cp->textsel = 1;
  571.         return;
  572.         }
  573.     }
  574. }
  575.  
  576.                     /* find new starting point for extending text selection */
  577. void addsel(short *downloc, cnr *cp)
  578. {
  579. short startoff, endoff;
  580. register short i;
  581.  
  582. for (i=0; i < cp->maxcnt; i++)            /* get first selection offset */
  583.     if ((cp->atrbuff)[i] & 0x0020) {
  584.         startoff = i;
  585.         break;        
  586.         }
  587. for (i=cp->maxoff; i >= 0; i--)
  588.     if ((cp->atrbuff)[i] & 0x0020) {
  589.         endoff = i;
  590.         break;
  591.         }
  592. if ((*downloc) < startoff)
  593.      (*downloc) = endoff + 1;
  594. else (*downloc) = startoff;
  595. }
  596.  
  597. void wordadj(short *loc1, short *loc2, char endadj, cnr *cp)
  598. {
  599. short startloc, endloc;
  600. short startline, endline;
  601. char swapped;
  602.  
  603. swapped = 0;
  604. startloc = *loc1;
  605. endloc = *loc2;
  606. if (startloc > endloc) {
  607.     startloc = *loc2;
  608.     endloc = *loc1;
  609.     swapped = 1;
  610.     }
  611. endloc -= endadj;
  612. if (endloc < 0) return;
  613.  
  614. startline = startloc/cp->scrhsize;
  615. endline = endloc/cp->scrhsize;
  616. while ((!atspace(startloc, cp)) && (startloc > 0) &&
  617.        ((startloc-1)/cp->scrhsize == startline)) startloc--;
  618. while ((atspace(startloc, cp)) && (startloc < endloc) &&
  619.        ((startloc+1)/cp->scrhsize <= endline)) startloc++;
  620. while ((!atspace(endloc, cp)) && (endloc < cp->maxoff) &&
  621.        ((endloc+1)/cp->scrhsize == endline)) endloc++;
  622. while ((atspace(endloc, cp)) && (endloc > startloc) &&
  623.        ((endloc-1)/cp->scrhsize >= startline)) endloc--;
  624. if (atspace(startloc, cp) && atspace(endloc, cp)) return;
  625.  
  626. endloc += endadj;
  627.  
  628. if (swapped) {
  629.     *loc2 = startloc;
  630.     *loc1 = endloc;
  631.     }
  632. else {
  633.     *loc1 = startloc;
  634.     *loc2 = endloc;
  635.     }
  636. }
  637.  
  638. short atspace(short loc, cnr *cp)
  639. {
  640. if ((cp->chrbuff)[loc] == 0x40) return(1);
  641. if ((cp->chrbuff)[loc] == 0x00) return(1);
  642. if ((cp->atrbuff)[loc] & 0x8000) return(1);
  643. return(0);
  644. }
  645.